/**
 * @class   wosh::network::NetworkChannelTcp
 * @brief   wosh::NetworkChannel implementation based on TCP protocol.
 *
 * @see     wosh::NetworkManager
 ****************************************************************************
 * @version $Id: NetworkChannelTcp.h 2584 2010-05-27 16:17:07Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Network_NetworkChannelTcp_H__
 #define __WOSH_Network_NetworkChannelTcp_H__

 #include <core/NetworkChannel.h>
 #include <core/Thread.h>

 #include <framework/network/SocketTcp.h>



namespace wosh {
 namespace network {

 #define _NetworkChannelTcp_KEY_Role			"Role"
 #define _NetworkChannelTcp_KEY_BufferSize		"BufferSize"

 #define _NetworkChannelTcp_RoleClient			"Client"
 #define _NetworkChannelTcp_RoleServer			"Server"

 #define _NetworkChannelTcp_BUFFER				32768 * 8

class NetworkProtocolTcp;

class NetworkChannelTcp :	protected wosh::ThreadImpl,
							public wosh::NetworkChannel,
							public virtual wosh::network::ISocketTcpListener
 {
	Q_OBJECT

	WOSH_CLASSNAME(wosh::network::NetworkChannelTcp)
	WOSH_CLASS_ABSTRACT(false)

	public:
		NetworkChannelTcp( const std::string& name = "" );

		virtual ~NetworkChannelTcp();

	public:
		virtual WRESULT connect( unsigned long timeout = LIMIT_ULONG_MAX );
		virtual WRESULT connect( const std::string& addressport, unsigned long timeout = LIMIT_ULONG_MAX );
		virtual WRESULT disconnect( unsigned long timeout = LIMIT_ULONG_MAX );

		virtual WRESULT sendMessage( const wosh::Message* message );
		virtual WRESULT sendData( const char* data, unsigned long size );

		virtual WRESULT ping( unsigned long timeout = 15000 );

		virtual WRESULT declarateWoshHost();

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		virtual bool isConnected() const;

		virtual std::string getProtocol() const;

		std::string getConnectedAddressPort() const;
		virtual const std::string& getRemoteWoshName() const  { return this->remoteWoshName; }

//@}
/** @name ISocketTcpListener
 * @{
 ******************************************************************************/
	public:
		virtual void tcpDataAvailable( long data_len, wosh::network::SocketTcp* socket );
		virtual void tcpSocketError( int error_code, const char* description, wosh::network::SocketTcp* socket );
//@}
/** @name Internal methods
 * @{
 ******************************************************************************/
	protected:
		// not a slot/reentrant, may be called only within socket events (tcpDataAvailable)
		void got_ping();
		void got_pong();

		void doDumpOutput();
		void doDumpInput( const char* data, long data_len );

		bool parseDataMessage( const char* data, long data_len );
		void parseChunk( long data_len, wosh::network::SocketTcp* socket );

		bool initializingThread();
		void runThread();
		void exitingThread();
//@}
	protected:
		bool handshaked;
		short ping_state;

		bool writing;
		char* msgBufferOut;
		int msgBufferOutSize;
		wosh::MutexRW msgBufferOutMux;

		char* msgBufferIn;
		wosh::MutexRW msgBufferInMux;
		int waitingPacketSize;
		int waitingBufferedSize;

		wosh::network::SocketTcp* tcpSocket;

		int socket_id;
		std::string remoteAddressPort;

		std::string remoteWoshName;

		friend class wosh::network::NetworkProtocolTcp;


	private slots:
		void writeData();

	signals:
		void writeData_s();
		void connect_s();


	private:
		NetworkChannelTcp(const NetworkChannelTcp&) : wosh::ThreadImpl(NULL), wosh::NetworkChannel() { }
		NetworkChannelTcp& operator=(const NetworkChannelTcp&) { return *this; }

}; // class def

 }; // namespace network
}; // namespace wosh

#endif //__WOSH_Network_NetworkChannelTcp_H__
